package base.core.security.dms;

import base.core.util.Beans;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.context.SecurityContextHolder;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Date;


import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import jakarta.servlet.http.HttpServletRequest;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

/**
 * @Description
 * @Author Pengwei
 * @CreatDate 2022/1/10 23:45
 */
@Slf4j
public class DmsJwtUtils {
    //DMS RSA256 私钥
    static String private_key = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKaTz4pgOR/p0RjlczM0dErf4ZUNziE/HJcfKDLPu77Gs2EJdDK0uGfPI3GX/eRwX9L9bTZJtz9sX2fkRqRt3gWnsMypT2P/cO/2GgtRCPHRFD7BI" +
            "+Df32isEJZ6M4kD9tyKLw8Y9KuP0C20ZMMDeCrrbjMagMMrwTOM4/4eFjzVAgMBAAECgYEAnH3mj2hgolOmhg4hkOxpiGIV6lMi4OcKtAqoWDwCdHL12GbqTCytxZC7Cp+w" +
            "/Wh5DZ3aeRL93c6xPsgdeaJh3kYa4ooo6b5tFHPU63VU5MBgwGzi26/6GB4GCXxGMB+SxmdigDmmPIYbXD+jO2oj1s8hj+DOE4U2fIjeZ" +
            "//DumECQQDlA74KHNZlKxoWl0FoHCgcIHFBZcQWKO3puhrH7VsRYI7CVVguE57NBT6QvAmU9r32PDt64tS0Qd1sCrk4uEqtAkEAujSj/cwF4ctQZCbUoMMzK/mw8ZxW3M6VK3urbq8fyFJ2iT2aLV3jE3+tnDdpezcfnbs/9SVXeFmJpdg" +
            "/L7hnyQJAQyxo1qCExmHxIgU1uyrfHPjrH2qRLIrO1gqvhkr5tkwjM59C4SkCIFLUejGdgeMp7wrVy4KzLzhOkT1H/PoZdQJAEbKxJ409veFKKcq7CPCkq3hXBg/a/a+w4+okOCfy+GJGG" +
            "/M79TXoQFExWhi2MNzjZ2WFxbIf5zNzbszn7Iw1aQJBAIXpKrQ0sLxr0rFzsoHBrobPcnQeutzypQNTPkoItILVP9pWz+aUfIKnOHEC5GAdD2LPZZ/pF7ixdRd9nBab+pk=";
    //DMS RSA256 公钥
    static String public_key = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmk8+KYDkf6dEY5XMzNHRK3+GVDc4hPxyXHygyz7u+xrNhCXQytLhnzyNxl/3kcF/S/W02Sbc/bF9n5Eakbd4Fp7DMqU9j/3Dv9hoLUQjx0RQ+wSPg399orBCWejOJA" +
            "/bcii8PGPSrj9AttGTDA3gq624zGoDDK8EzjOP+HhY81QIDAQAB";

    public static final String TOKEN_HEADER = "Authorization";
    public static final String TOKEN_PREFIX = "Bearer";

    public static final long EXPIRITION = 1000 * 24 * 60 * 60 * 7;

    /**
     * 生成token
     */
    public static String createToken(String username, String userId) {
        String token = Jwts
                .builder()
                .setSubject(username)
                .claim("sub", username)
                .claim("userId", userId)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRITION))
                .signWith(SignatureAlgorithm.RS256, getPrivateKey(private_key)).compact();
        return token;
    }

    /**
     * 判断token是否有效
     */
    public static boolean isValid(String token) {
        if (getTokenInfo(token) != null) {
            return true;
        }
        return false;
    }

    /**
     * 获取token信息
     */
    public static DmsTokenInfo getTokenInfo() {
        try {
            DmsTokenInfo tokenInfo = (DmsTokenInfo) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            return tokenInfo;
        } catch (Exception e) {
            log.error("获取token信息错误", e);
        }
        return null;
    }

    /**
     * 获取token信息
     */
    public static DmsTokenInfo getTokenInfo(String token) {
        try {
            if (StringUtils.isBlank(token)) {
                return null;
            }
            Claims claims = Jwts.parser().setSigningKey(getPublicKey(public_key)).parseClaimsJws(token).getBody();
            DmsTokenInfo tokenInfo = Beans.asObj(claims, DmsTokenInfo.class);
            tokenInfo.setToken(token);
            return tokenInfo;
        } catch (Exception e) {
            log.error("获取token信息错误", e);
            return null;
        }
    }

    /**
     * 获取token信息
     */
    public static DmsTokenInfo getTokenInfo(HttpServletRequest request) {
        String tokenHeader = request.getHeader(DmsJwtUtils.TOKEN_HEADER);
        if (StringUtils.isBlank(tokenHeader)) {
            return null;
        }
        String token = tokenHeader.replace(DmsJwtUtils.TOKEN_PREFIX, "").trim();
        DmsTokenInfo tokenInfo = getTokenInfo(token);
        return tokenInfo;
    }

    @SneakyThrows
    public static PublicKey getPublicKey(String publicKeyBase64) {
        byte[] byteKey = Base64.decodeBase64(publicKeyBase64);
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(byteKey);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(x509EncodedKeySpec);
    }

    @SneakyThrows
    private static PrivateKey getPrivateKey(String privateKeyBase64) {
        byte[] byteKey = Base64.decodeBase64(privateKeyBase64);
        PKCS8EncodedKeySpec x509EncodedKeySpec = new PKCS8EncodedKeySpec(byteKey);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(x509EncodedKeySpec);
    }


    public static void main(String[] args) {
        String admin = createToken("admin", "0100");
        System.out.println("Authorization");
        System.out.println(admin);
        System.out.println("Bearer " + admin);
    }

}